/*
 *  AS IS License 
 * ==Naive Coders==
 */
package com.naivecoders.refex.functions;

import com.naivecoders.refex.FunctionFactory;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author andrew
 */
public class SubstituteArgumentsFunction extends AbstractFunction {

    public SubstituteArgumentsFunction(FunctionFactory origin) {
        super(origin);
    }

    @Override
    public AbstractFunction evaluate(ListFunction x) throws InvocationException {
        final ListFunction func = substituteArgs(listArg(x, 0), x.tail());
        return func;
    }

    private boolean isArgument(AbstractFunction f) throws InvocationException {
        if (f instanceof ListFunction) {
            final ListFunction fl = (ListFunction) f;
            return !fl.isEmpty() && fl.head() instanceof ArgumentFunction;
        }
        return false;
    }

    private int getArgumentIndex(AbstractFunction f) {
        return ((ListFunction) f).size() - 2;
    }

    private ListFunction shiftedArgument(AbstractFunction as, int amount) {
        return ((ListFunction)as).drop(amount);
       
    }
    
    private ListFunction substituteArgs(ListFunction where, ListFunction argValues) throws InvocationException {
        final List<AbstractFunction> result = new ArrayList<>();
        for (AbstractFunction af : where) {
            if (isArgument(af)) {
                final int argIndex = getArgumentIndex(af);
                if (argValues.size() <= argIndex) {// curry
                    result.add(shiftedArgument(af,argIndex - argValues.size()));
                } else {
                    result.add(argRaw(argValues, argIndex));
                }
            } else if (af instanceof ListFunction) {
                result.add(substituteArgs((ListFunction) af, argValues));
            } else {
                result.add(af);
            }
        }
        return getOrigin().list(result);
    }
}
